-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Image][Performance] Fast Image with Auth Token Header Caching #12648
[Image][Performance] Fast Image with Auth Token Header Caching #12648
Conversation
CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅ |
@aldo-expensify Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
I have read the CLA Document and I hereby sign the CLA |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please commit suggestion to fix linter errors
@thomas-coldwell can you retroactively sign your commits? please We will also need you to complete the PR Author steps:
Thanks! Asked here about it: #10792 (comment) |
Will get those sorted now @aldo-expensify cheers! |
15bc0dc
to
df2ded5
Compare
Signed-off-by: Thomas Coldwell <[email protected]>
Signed-off-by: Thomas Coldwell <[email protected]>
Co-authored-by: Aldo Canepa Garay <[email protected]> Signed-off-by: Thomas Coldwell <[email protected]>
df2ded5
to
98c2590
Compare
Looks like we need to have a think about how this should work on Desktop and Web (inc. mWeb) before this PR is merged cc @Beamanator |
Yo @thomas-coldwell so correct me if I'm wrong but I had two assumptions in regard to web / desktop:
|
Hey @Beamanator you are correct - there is no implementation of |
Sorry I am going OOO, so I won't be able to take this. Please re-assign. |
🚀 Deployed to staging by @Beamanator in version: 1.2.31-0 🚀
|
@thomas-coldwell Seems like this PR has introduced a deploy blocker. Looking into this. I will prepare a revert of this PR if the solution is not obvious. |
Revert "Merge pull request #12648 from margelo/@thomas/fast-image-cac…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this was reverted and I studied the logic a bit, I'll leave a review to help the next PR
I have a question about the name FastImage
Why was it decided to call App's component FastImage
instead of simply Image
Due to the differences in platform code, some confusion and quirks exists
onLoad
is called with one parameter structure inFastImage
and another inreact-native
(web) Image
(FastImage onLoad | RN onLoad)FastImage
has different static methods exposed and methods likepreload
acceptsource
and evensource
array, while in RN it's just auri: string
When I see FastImage
I would assume all the react-native-fast-image
options are available to this component, but since our FastImage
implementation for web/desktop so far is only a core Image
component they won't work
I think it a possible improvement for a follow up PR is to
- use a simple name like
Image
orAppImage
for the component - add a specific
propTypes.js
interface that implement only the minimum props we use
This way we can declare the source
we support ATM is number | string | { urI: string, headers: object }
e.g. nothing conflicting with the differences between source structure between FastImage
and regular Image
I think the change is necessary, because
- we might or might not update
react-native-fast-image
with (full) support forweb
- it might take time or not be a priority to apply these updates to
react-native-fast-image
- so a clean interface of exactly what we use would be helpful in maintaining the cross platform App Image component
@@ -115,7 +115,7 @@ class AttachmentModal extends PureComponent { | |||
* @param {String} sourceURL | |||
*/ | |||
downloadAttachment(sourceURL) { | |||
fileDownload(sourceURL, this.props.originalFileName); | |||
fileDownload(this.props.isAuthTokenRequired ? addEncryptedAuthTokenToURL(sourceURL) : sourceURL, this.props.originalFileName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Beamanator
We can update fileDownload
to also work with headers.
Not sure whether any backend handling would need to be updated
making fileDownload
work with headers is not as important as images, because it's used a lot less often
on the other hand the logic would be cleaner and allow automatic cache usage
} | ||
|
||
render() { | ||
const headers = this.props.isAuthTokenRequired ? chatAttachmentTokenHeaders() : undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO it might be better to forward isAuthTokenRequired
to the Image
and let the Image
run this logic instead of having it repeat for any subtype of Image we have
export default withOnyx({ | ||
session: {key: ONYXKEYS.SESSION}, | ||
})(ImageWithSizeCalculation); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As pointed out in another comment - this is unused
|
||
let encryptedAuthToken = ''; | ||
Onyx.connect({ | ||
key: ONYXKEYS.SESSION, | ||
callback: session => encryptedAuthToken = lodashGet(session, 'encryptedAuthToken', ''), | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Beamanator
This is not the "React Way" to deal with global or storage state
It's a bit of an antipattern actually because it doesn't integrate with component lifecycle - only a re-render would cause users of chatAttachmentTokenHeaders
to re-evaluate, but the change in ONYXKEYS.SESSION
would not trigger a re-render, unless the component is also subscribed to session
The "React Way" is to capture this with withOnyx
so the component is subscribed to session and re-evaluates headers the moment they change
To keep it simple the withOnyx
can be applied on the core Image
(FastImage) component and let it perform the logic from this file
I know we use the static Onyx.connect
logic for other cases, but we should distinct the cases that really need it and the cases that can use withOnyx
instead
Another bad thing about the static pattern is that it is static - we can't lazy load it and the connection stays forever, while using the "React Way" would free resources
- the connection can be initiated only when needed
- the connection is released when the component is no longer mounted
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gooooood points, I overlooked those lifecycle points & didn't think about lazy loading / freeing resources, I'll definitely keep those in mind in the future! Next round will not do this this way ;D
🚀 Deployed to staging by @Beamanator in version: 1.2.32-0 🚀
|
cc @thomas-coldwell, thanks for the review @kidroca |
For the next round of QA, @Beamanator @aldo-expensify can we get a regression test suite from Testrail to ensure nothing breaks! |
🚀 Deployed to production by @luacmartins in version: 1.2.32-2 🚀
|
🚀 Deployed to production by @luacmartins in version: 1.2.32-2 🚀
|
@kidroca thanks for the review, I'll also request your review on the follow-up PR when it's ready :D 🙏
I thought It looks like we currently often use standard react native component names when we customize them, and if we want to directly use a react native component (like @thomas-coldwell When the follow-up PR is ready can you please tag me & request a review from @kidroca as well please? 👍 |
Hey @kidroca @Beamanator thanks for those points!
I'll link the follow-up PR here shortly and make sure you are both set to review it :) |
Just addressing the issue on Android that caused this PR to be reverted and hoping you might be able to provide a bit more context around this. The issue originated from the fact that
As a result the initial width/height for the thumbnail component (specifically in the case of a PDF thumbnail) style will always be zero and this is never updated or corrected by the I will continue to see what can be solved on the |
Innnteresting findings @thomas-coldwell ! I just found in our back-end code, we currently use PHP's getfilesize function to try to get the file size (here, for internal employees). And because this doesn't actually work for @thomas-coldwell what I'm planning to try next is:
|
Cool I followed steps 1 & 2, tested with the old code, things looked good! I hard-coded to 30px by 30px in the test which is why it turned out so small, but I will tweak it so it looks fine & I'll test on other platforms to make sure it doesn't break anything while we're waiting for the next version of @thomas-coldwell 's PR Screen.Recording.2022-12-02.at.3.35.22.PM.mov |
@Beamanator the code to proceed the upload is same for OldDot as well, right. does it parse receipts too? we should probably try to avoid manipulating that flow now if that is the case. |
@vitHoracek here's the draft PR: https://github.com/Expensify/Web-Expensify/pull/35730 the code is only used when adding comments to reports, so I don't think it parses receipts 'n such, but feel free to comment on that PR if you have concerns! I'm still working on testing that it doesn't break things :D |
@Beamanator no problem, I trust you :D just wanted to raise this |
Thanks @Beamanator and @mountiny - great that this change server-side does ensure a non-zero width and height. I will get the changes in for the Fast Image |
That would be very helpful, thanks @thomas-coldwell ! |
Here's the draft PR @Beamanator - just travelling atm, but started doing some digging on the revert issue #13304 😃 |
Thanks @thomas-coldwell ! Will respond in that new PR 👍 |
Details
This PR combines the draft PR from @Szymon20000 #11009 for adding fast image and the PoC auth token PR from @Beamanator #12146 to properly cache images using fast image with the auth token being passed in the headers rather than the URL.
Fixed Issues
#10792
$ GH_LINK
PROPOSAL: GH_LINK_ISSUE(COMMENT)
Tests
QA Steps
PR Author Checklist
### Fixed Issues
section aboveTests
sectionQA steps
sectiontoggleReport
and notonIconClick
)src/languages/*
filesWaiting for Copy
label for a copy review on the original GH to get the correct copy.STYLE.md
) were followedAvatar
, I verified the components usingAvatar
are working as expected)/** comment above it */
this
properly so there are no scoping issues (i.e. foronClick={this.submit}
the methodthis.submit
should be bound tothis
in the constructor)this
are necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);
ifthis.submit
is never passed to a component event handler likeonClick
)StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG
)Avatar
is modified, I verified thatAvatar
is working as expected in all cases)PR Reviewer Checklist
The reviewer will copy/paste it into a new comment and complete it after the author checklist is completed
### Fixed Issues
section aboveTests
sectionQA steps
sectiontoggleReport
and notonIconClick
).src/languages/*
filesWaiting for Copy
label for a copy review on the original GH to get the correct copy.STYLE.md
) were followedAvatar
, I verified the components usingAvatar
have been tested & I retested again)/** comment above it */
this
properly so there are no scoping issues (i.e. foronClick={this.submit}
the methodthis.submit
should be bound tothis
in the constructor)this
are necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);
ifthis.submit
is never passed to a component event handler likeonClick
)StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG
)Avatar
is modified, I verified thatAvatar
is working as expected in all cases)Screenshots
Web
Mobile Web - Chrome
Mobile Web - Safari
Desktop
iOS
Android